home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 23
/
AACD 23.iso
/
AACD
/
Online
/
opennap
/
timer.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-08
|
3KB
|
138 lines
/* Copyright (C) 2000 edwards@bitchx.dimension6.com
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
Modified by drscholl@users.sourceforge.net 2/29/2000.
$Id: timer.c,v 1.9 2001/02/13 08:41:15 drscholl Exp $ */
#include <time.h>
#include <stdlib.h>
#include "opennap.h"
#include "debug.h"
typedef struct _timerstruct
{
struct _timerstruct *next;
timer_cb_t func;
void *arg;
time_t next_time;
time_t interval;
int events;
unsigned int refnum;
}
TIMER;
static TIMER *Pending_Timers = NULL;
static unsigned int TimerRef = 0;
static void
schedule_timer (TIMER * ntimer)
{
TIMER **slot;
if (!ntimer->events)
return;
/* we've created it, now put it in order */
for (slot = &Pending_Timers; *slot; slot = &(*slot)->next)
{
if (ntimer->next_time < (*slot)->next_time)
break;
}
ntimer->next = *slot;
*slot = ntimer;
}
/* returns the refnum */
int
add_timer (int interval, int events, timer_cb_t func, void *arg)
{
TIMER *new;
if (!events)
return -1;
new = CALLOC (1, sizeof (TIMER));
if (!new)
{
OUTOFMEMORY ("add_timer");
return -1;
}
new->next_time = global.current_time + interval;
new->interval = interval;
new->func = func;
new->arg = arg;
new->events = events;
new->refnum = TimerRef++;
schedule_timer (new);
return new->refnum;
}
void
exec_timers (time_t now)
{
TIMER *current;
while (Pending_Timers && Pending_Timers->next_time <= now)
{
current = Pending_Timers;
Pending_Timers = current->next;
(*current->func) (current->arg);
switch (current->events)
{
case 0:
FREE (current);
break;
default:
current->events--;
case -1:
/* reschedule */
current->next_time = global.current_time + current->interval;
schedule_timer (current);
break;
}
}
}
/* returns the time offset at which the next pending event is scheduled */
time_t next_timer (void)
{
if (Pending_Timers)
{
if (Pending_Timers->next_time < global.current_time)
return 0; /* now! */
return (Pending_Timers->next_time - global.current_time);
}
return -1;
}
void
free_timers (void)
{
TIMER *ptr;
while (Pending_Timers)
{
ptr = Pending_Timers;
Pending_Timers = Pending_Timers->next;
FREE (ptr);
}
}
/* change the interval at which a timer occurs. note that this does not
* reschedule a currently pending event, and only affect subsequent calls
*/
void
timer_set_interval (unsigned int refnum, int interval)
{
TIMER *t = Pending_Timers;
for (; t; t = t->next)
if (t->refnum == refnum)
{
t->interval = interval;
break;
}
}